﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using Microsoft.Reporting.WinForms;
using WpfApp1.Report;

namespace WpfApp1
{
    class RDLCPrint : IDisposable
    {

          // public RDLCPrint()
          // {
          //
          //
          // 
          //
          // }


        public RDLCPrint(bool detail1,bool detail2)
        {
            isDetail1 = detail1;
            isDetail2 = detail2;



        }


        SQLiteHelper sqlite = new SQLiteHelper();

        private bool debug = true;

           // int paper_width = 350;
           // int paper_height = 400;
            /// <summary>
            /// 当前打印页号
            /// </summary>
            static int m_currentPageIndex;

            /// <summary>
            /// RDCL转换stream一页对应一个stream
            /// </summary>
            static List<Stream> m_streams;

            /// <summary>
            /// 把report输出成stream
            /// </summary>
            /// <param name="report">传入需要Export的report</param>
            private void Export(LocalReport report)
            {
                string deviceInfo =
                  "<DeviceInfo>" +
                  "  <OutputFormat>EMF</OutputFormat>" +
                  // "  <PageWidth>25cm</PageWidth>" +
                  // "  <PageHeight>25cm</PageHeight>" +
                   "  <MarginTop>0cm</MarginTop>" +
                   "  <MarginLeft>0cm</MarginLeft>" +
                   "  <MarginRight>0cm</MarginRight>" +
                   "  <MarginBottom>0cm</MarginBottom>" +
                  "</DeviceInfo>";
                Warning[] warnings;
                m_streams = new List<Stream>();
            try
            {
                report.Render("Image", deviceInfo, CreateStream, out warnings);
            }
            catch
            {

            }

            try
            {
                foreach (Stream stream in m_streams)
                {
                    stream.Position = 0;
                }
            }
            catch
            {

            }


            }

            /// <summary>
            /// 创建具有指定的名称和格式的流。
            /// </summary>
            private Stream CreateStream(string name, string fileNameExtension,
          Encoding encoding, string mimeType, bool willSeek)
            {
            Stream stream = null;
            try
            {
                 stream=new FileStream(name + "." + fileNameExtension,
                  FileMode.Create);

                m_streams.Add(stream);

            }
            catch
            {

            }
                
             return stream;
            }

            /// <summary>
            /// 打印输出
            /// </summary>
            private void PrintPage(object sender, PrintPageEventArgs ev)
            {
                Metafile pageImage =
                  new Metafile(m_streams[m_currentPageIndex]);


           // ev.PageSettings.PaperSize = new System.Drawing.Printing.PaperSize("Custom", paper_width, paper_height);
           
            // ev.Graphics.DrawImage(pageImage, ev.PageBounds, 0, 0, ev.PageBounds.Width, ev.PageBounds.Height, System.Drawing.GraphicsUnit.Pixel);

             ev.Graphics.DrawImage(pageImage, ev.PageBounds);

                m_currentPageIndex++;
                ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
            }

            /// <summary>
            /// 打印预处理
            /// </summary>
            private void Print(string printerName,string orderid,short copies,int paper_width,int paper_height)
        {

            try
            {
                excuteCmd(" net start Spooler ");
            }
            catch
            {

            }
            PrintDocument printDoc = new PrintDocument();
                //string printerName = printDoc.PrinterSettings.PrinterName;
                if (m_streams == null || m_streams.Count == 0)
                    return;
                printDoc.PrinterSettings.PrinterName = printerName;
            printDoc.DefaultPageSettings.Margins.Top = 0;
            printDoc.DefaultPageSettings.Margins.Bottom = 0;
            printDoc.DefaultPageSettings.Margins.Left = 0;
            printDoc.DefaultPageSettings.Margins.Right = 0;
            
            printDoc.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("Custom", paper_width, paper_height);
              //  printDoc.DefaultPageSettings.Margins.Top = 0;
                printDoc.DefaultPageSettings.PrinterSettings.Copies = copies;
                //printDoc.DefaultPageSettings.PrinterSettings.Copies =1;
            if (!printDoc.PrinterSettings.IsValid)
                {
                    string msg = String.Format("Can't find printer \"{0}\".", printerName);
                    //MessageBox.Show(msg);
                    return;
                }
                printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
                StandardPrintController spc = new StandardPrintController();
                printDoc.PrintController = spc;
            try
            {
                int stat=Printer.GetPrinterStatusInt(printerName);
                if (stat == 0)
                {
                    try
                    {
                        printDoc.Print();
                        string sql = "update 'order' set status='3' where id='" + orderid + "' ";
                        if (isDetail1) {
                            sql = "update 'order_detail' set status='3' where id='" + orderid + "' ";
                            
                        }
                        sqlite.update(sql);

                    }
                    catch
                    {
                        Console.WriteLine("打印失败 order id="+orderid);
                    }
                    
                }
            }
            catch
            {

            }
            }



        public static string excuteCmd(string cmd)
        {
            Process proc = new Process();
            proc.StartInfo.FileName = "cmd.exe";
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardInput = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.Arguments = "/c " + cmd;
            proc.Start();
            proc.WaitForExit();
            string ret = "";// proc.StandardOutput.ReadToEnd() + proc.StandardError.ReadToEnd();
            //Console.WriteLine(ret);
            return ret;
        }
        

        private void Print2(string printerName, string orderid,short copies,int paper_width,int paper_height)
        {
            try
            {
                excuteCmd(" net start Spooler ");
            }
            catch
            {

            }
            PrintDocument printDoc = new PrintDocument();
            //string printerName = printDoc.PrinterSettings.PrinterName;
            if (m_streams == null || m_streams.Count == 0)
                return;
            printDoc.PrinterSettings.PrinterName = printerName;
            printDoc.DefaultPageSettings.Margins.Top = 0;
            printDoc.DefaultPageSettings.Margins.Bottom = 0;
            printDoc.DefaultPageSettings.Margins.Left = 0;
            printDoc.DefaultPageSettings.Margins.Right = 0;
            printDoc.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("Custom", paper_width, paper_height);

            printDoc.DefaultPageSettings.PrinterSettings.Copies = copies;
            //printDoc.DefaultPageSettings.PrinterSettings.Copies = 1;
            if (!printDoc.PrinterSettings.IsValid)
            {
                string msg = String.Format("Can't find printer \"{0}\".", printerName);
                //MessageBox.Show(msg);
                return;
            }
            printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
            StandardPrintController spc = new StandardPrintController();
            
            printDoc.PrintController = spc;
            try
            {
                int stat = Printer.GetPrinterStatusInt(printerName);
                if (stat == 0)
                {
                    try
                    {
                        printDoc.Print();
                        SQLiteHelper sqlite = new SQLiteHelper();

                        string sql = "update 'order_out' set status='3' where id='" + orderid + "' ";
                        if (this.isDetail2)
                        {
                            sql = "update 'order_out_detail' set status='3' where id='" + orderid + "' ";
                           
                        }
                        sqlite.update(sql);


                        // sqlite.update("update 'order_out' set status='3' where id='" + orderid + "' ");
                    }
                    catch
                    {
                        Console.WriteLine("打印失败 order_out id="+orderid);
                    }
                }
            }
            catch
            {

            }
        }

        public void Dispose()
            {
                if (m_streams != null)
                {
                    foreach (Stream stream in m_streams)
                        stream.Close();
                    m_streams = null;
                }
            }

        public bool isDetail1 { get; set; }
        public bool isDetail2 { get; set; }

        /// <summary>
        /// 对外接口,启动打印
        /// </summary>
        /// <param name="dtSource">打印报表对应的数据源</param>
        /// <param name="sReport">打印报表名称</param>
        public  void Run(LocalReport report,string dataset,List<Orders> orders, List<ReportParameter> pr, string printerName,string orderid,string copies,int paper_width,int paper_height)
        {
            //LocalReport report = new LocalReport();
            //report.ReportPath = @"..\..\" + sReport;
            //ReportDataSource dataset = new ReportDataSource("DataSet1", dtSource);
            //report.DataSources.Add(dataset);
            

            report.DataSources.Add(new ReportDataSource(dataset, orders));

            if (pr != null)
            {
                for (int i = 0; i < pr.Count; i++)
                {
                    try
                    {
                        report.SetParameters(pr[i]);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("error:" + ex.Message);
                    }
                }
            }

            m_currentPageIndex = 0;
                RDLCPrint billPrint = new RDLCPrint(isDetail1,isDetail2);
            
            billPrint.Export(report);

            short cp = 1;

            try
            {
                cp=short.Parse(copies);
            }
            catch
            {
                cp = 1;
            }
            if (cp <= 0)
            {
                cp = 1;
            }


            billPrint.Print(printerName,orderid,cp, paper_width, paper_height);
                 
            
                billPrint.Dispose();
            }

        public  void Run2(LocalReport report, string dataset, List<Orders> orders, List<ReportParameter> pr, string printerName, string orderid,string copies,int paper_width,int paper_height)
        {
            //LocalReport report = new LocalReport();
            //report.ReportPath = @"..\..\" + sReport;
            //ReportDataSource dataset = new ReportDataSource("DataSet1", dtSource);
            //report.DataSources.Add(dataset);

            

            report.DataSources.Add(new ReportDataSource(dataset, orders));

            if (pr != null)
            {
                for (int i = 0; i < pr.Count; i++)
                {
                    try
                    {
                        report.SetParameters(pr[i]);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("error:" + ex.Message);
                    }
                }
            }

            m_currentPageIndex = 0;
            RDLCPrint billPrint = new RDLCPrint(isDetail1,isDetail2);
            billPrint.Export(report);
            short cp = 1;

            try
            {
                cp = short.Parse(copies);
            }
            catch
            {
                cp = 1;
            }
            if (cp <= 0)
            {
                cp = 1;
            }
            billPrint.Print2(printerName, orderid,cp, paper_width, paper_height);


            billPrint.Dispose();
        }


        public  void Run(LocalReport report, string dataset, List<Orders2> orders, List<ReportParameter> pr, string printerName, string orderid,string copies,int paper_width,int paper_height)
        {
            //LocalReport report = new LocalReport();
            //report.ReportPath = @"..\..\" + sReport;
            //ReportDataSource dataset = new ReportDataSource("DataSet1", dtSource);
            //report.DataSources.Add(dataset);

            report.DataSources.Add(new ReportDataSource(dataset, orders));

            if (pr != null)
            {
                for (int i = 0; i < pr.Count; i++)
                {
                    try
                    {
                        report.SetParameters(pr[i]);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("error:" + ex.Message);
                    }
                }
            }

            m_currentPageIndex = 0;
            RDLCPrint billPrint = new RDLCPrint(isDetail1,isDetail2);
            billPrint.Export(report);
            short cp = 1;

            try
            {
                cp = short.Parse(copies);
            }
            catch
            {
                cp = 1;
            }
            if (cp <= 0)
            {
                cp = 1;
            }
            billPrint.Print(printerName, orderid,cp, paper_width, paper_height);


            billPrint.Dispose();
        }

        public  void Run2(LocalReport report, string dataset, List<Orders2> orders, List<ReportParameter> pr, string printerName, string orderid,string copies,int paper_width,int paper_height)
        {
            //LocalReport report = new LocalReport();
            //report.ReportPath = @"..\..\" + sReport;
            //ReportDataSource dataset = new ReportDataSource("DataSet1", dtSource);
            //report.DataSources.Add(dataset);

            report.DataSources.Add(new ReportDataSource(dataset, orders));

            if (pr != null)
            {
                for (int i = 0; i < pr.Count; i++)
                {
                    try
                    {
                        report.SetParameters(pr[i]);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("error:" + ex.Message);
                    }
                }
            }

            m_currentPageIndex = 0;
            RDLCPrint billPrint = new RDLCPrint(isDetail1,isDetail2);
            billPrint.Export(report);
            short cp = 1;

            try
            {
                cp = short.Parse(copies);
            }
            catch
            {
                cp = 1;
            }
            if (cp <= 0)
            {
                cp = 1;
            }
            billPrint.Print2(printerName, orderid,cp, paper_width, paper_height);


            billPrint.Dispose();
        }


        /// <summary>
        /// 获取打印机状态
        /// </summary>
        /// <param name="printerName">打印机名称</param>
        /// <param name="status">输出打印机状态</param>
        private static void GetPrinterStatus2(string printerName, ref uint status)
            {
                try
                {

                    string lcPrinterName = printerName;
                    IntPtr liHandle = IntPtr.Zero;
                    if (!Win32.OpenPrinter(lcPrinterName, out liHandle, IntPtr.Zero))
                    {
                        Console.WriteLine("print  is close");
                        return;
                    }
                    UInt32 level = 2;
                    UInt32 sizeNeeded = 0;
                    IntPtr buffer = IntPtr.Zero;
                    Win32.GetPrinter(liHandle, level, buffer, 0, out sizeNeeded);
                    buffer = Marshal.AllocHGlobal((int)sizeNeeded);
                    if (!Win32.GetPrinter(liHandle, level, buffer, sizeNeeded, out sizeNeeded))
                    {
                        Console.WriteLine(Environment.NewLine + "Fail GetPrinter:" + Marshal.GetLastWin32Error());
                        return;
                    }

                    Win32.PRINTER_INFO_2 info = (Win32.PRINTER_INFO_2)Marshal.PtrToStructure(buffer, typeof(Win32.PRINTER_INFO_2));
                    status = info.Status;
                    Marshal.FreeHGlobal(buffer);
                    Win32.ClosePrinter(liHandle);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

            /// <summary>
            /// 对外接口,调去打印机信息
            /// </summary>
            /// <param name="printerName">打印机名称</param>
            /// <returns>返回打印机当前状态</returns>
            public static string GetPrinterStatus(string printerName)
            {
                uint intValue = 0;
                PrintDocument pd = new PrintDocument();
                printerName = printerName == "" ? pd.PrinterSettings.PrinterName : printerName;
                GetPrinterStatus2(printerName, ref intValue);
                string strRet = string.Empty;
                switch (intValue)
                {
                    case 0:
                        strRet = "准备就绪（Ready）";
                        break;
                    case 4194432:
                        strRet = "被打开（Lid Open）";
                        break;
                    case 144:
                        strRet = "打印纸用完（Out of Paper）";
                        break;
                    case 4194448:
                        strRet = "被打开并且打印纸用完（Out of Paper && Lid Open）";
                        break;
                    case 1024:
                        strRet = "打印中（Printing）";
                        break;
                    case 32768:
                        strRet = "初始化（Initializing）";
                        break;
                    case 160:
                        strRet = "手工送纸(Manual Feed in Progress)";
                        break;
                    case 4096:
                        strRet = "脱机(Offline)";
                        break;
                    default:
                        strRet = "未知状态（unknown state）";
                        break;
                }
                return strRet;
            }
        }
        public class Win32
        {
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool OpenPrinter(string printer, out IntPtr handle, IntPtr printerDefaults);
            [DllImport("winspool.drv")]
            public static extern bool ClosePrinter(IntPtr handle);
            [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool GetPrinter(IntPtr handle, UInt32 level, IntPtr buffer, UInt32 size, out UInt32 sizeNeeded);
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct PRINTER_INFO_2
            {
                public string pServerName;
                public string pPrinterName;
                public string pShareName;
                public string pPortName;
                public string pDriverName;
                public string pComment;
                public string pLocation;
                public IntPtr pDevMode;
                public string pSepFile;
                public string pPrintProcessor;
                public string pDatatype;
                public string pParameters;
                public IntPtr pSecurityDescriptor;
                public UInt32 Attributes;
                public UInt32 Priority;
                public UInt32 DefaultPriority;
                public UInt32 StartTime;
                public UInt32 UntilTime;
                public UInt32 Status;
                public UInt32 cJobs;
                public UInt32 AveragePPM;
            }
        }
    }



